package org.colafries.admin.service.impl.index;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import org.apache.commons.collections4.CollectionUtils;
import org.colafries.admin.entity.domain.index.AtomicMetric;
import org.colafries.admin.entity.domain.index.LogicCondition;
import org.colafries.admin.entity.domain.index.LogicFactTable;
import org.colafries.admin.entity.vo.index.LogicFactTblReqVO;
import org.colafries.admin.exceptions.ServiceException;
import org.colafries.admin.exceptions.enums.ErrorCodeEnum;
import org.colafries.admin.mapper.index.AtomicMetricMapper;
import org.colafries.admin.mapper.index.LogicConditionMapper;
import org.colafries.admin.mapper.index.LogicFactTableMapper;
import org.colafries.admin.service.index.ILogicFactTableService;
import org.colafries.common.constants.Constants;
import org.colafries.common.enums.Flag;
import org.colafries.common.snowflake.SnowFlake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 逻辑事实表 服务实现类
 * </p>
 *
 * @author Ann
 * @since 2024-06-03
 */
@Service
public class ILogicFactTableServiceImpl extends ServiceImpl<LogicFactTableMapper, LogicFactTable> implements ILogicFactTableService {

    @Autowired
    LogicFactTableMapper logicFactTableMapper;
    @Autowired
    AtomicMetricMapper atomicMetricMapper;
    @Autowired
    LogicConditionMapper logicConditionMapper;

    @Override
    public int add(LogicFactTblReqVO vo) {
        long code = SnowFlake.nextId();
        LogicFactTable logicFactTable = LogicFactTable.builder()
                .code(code)
                .version(Constants.VERSION_FIRST)
                .logicTableName(vo.getLogicTableName())
                .logicTableAlias(vo.getLogicTableAlias())
                .logicPrimaryKey(vo.getLogicPrimaryKey())
                .sourceDbId(vo.getSourceDbId())
                .sourceSchema(vo.getSourceSchema())
                .sourceTableName(vo.getSourceTableName())
                .expression(vo.getExpression())
                .createUser(vo.getCreateUser())
                .updateUser(vo.getUpdateUser())
                .build();
        return logicFactTableMapper.insert(logicFactTable);
    }

    @Override
    public int update(LogicFactTblReqVO vo) {
        String logicTableCode = vo.getLogicTableCode();
        LambdaQueryWrapper<LogicFactTable> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LogicFactTable::getCode, logicTableCode);
        LogicFactTable logicFactTable = logicFactTableMapper.selectOne(queryWrapper);
        if (null == logicFactTable) {
            throw new ServiceException(ErrorCodeEnum.GL999999, "逻辑事实表修改失败，逻辑事实表code不存在，code:" + logicTableCode);
        }
        LogicFactTable logicFactTableNew = LogicFactTable.builder()
                .version(logicFactTable.getVersion() + 1)
                .logicTableName(vo.getLogicTableName())
                .logicTableAlias(vo.getLogicTableAlias())
                .logicPrimaryKey(vo.getLogicPrimaryKey())
                .sourceDbId(vo.getSourceDbId())
                .sourceSchema(vo.getSourceSchema())
                .sourceTableName(vo.getSourceTableName())
                .expression(vo.getExpression())
                .updateUser(vo.getUpdateUser())
                .build();
        return logicFactTableMapper.update(logicFactTableNew, queryWrapper);
    }

    @Override
    public int delete(LogicFactTblReqVO vo) {
        String logicTableCode = vo.getLogicTableCode();
        //判断逻辑事实表是否存在
        LambdaQueryWrapper<LogicFactTable> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LogicFactTable::getCode, logicTableCode);
        LogicFactTable logicFactTable = logicFactTableMapper.selectOne(queryWrapper);
        if (null == logicFactTable) {
            throw new ServiceException(ErrorCodeEnum.GL999999, "逻辑事实表删除失败，逻辑事实表code不存在，code:" + logicTableCode);
        }
        //判断逻辑事实表是否被使用
        if (Flag.YES == getLogicFactTblUsedFlag(logicTableCode)) {
            throw new ServiceException(ErrorCodeEnum.GL999999, "逻辑事实表删除失败，逻辑事实表被使用，code:" + logicTableCode);
        }
        return logicFactTableMapper.delete(queryWrapper);
    }

    /**
     * 判断逻辑事实表是否被原子指标、业务限定引用
     * @param logicTableCode
     * @return org.colafries.common.enums.Flag
     * @Author anning
     * @Date 2024/6/5
     */
    private Flag getLogicFactTblUsedFlag(String logicTableCode) {
        // 是否被原子指标引用
        List<AtomicMetric> atomicMetricList = atomicMetricMapper.selectList(
                Wrappers.<AtomicMetric>lambdaQuery().eq(AtomicMetric::getLogicTableCode, logicTableCode)
        );
        if (CollectionUtils.isEmpty(atomicMetricList)) {
            return Flag.NO;
        }
        //是否被业务限定引用
        List<LogicCondition> logicConditionList = logicConditionMapper.selectList(
                Wrappers.<LogicCondition>lambdaQuery().eq(LogicCondition::getLogicTableCode, logicTableCode)
        );
        if (CollectionUtils.isEmpty(logicConditionList)) {
            return Flag.NO;
        }
        return Flag.YES;
    }

    @Override
    public List<LogicFactTable> listAll(LogicFactTblReqVO vo) {
        return logicFactTableMapper.selectList(null);
    }

    @Override
    public IPage<LogicFactTable> pageList(LogicFactTblReqVO vo) {
        LambdaQueryWrapper<LogicFactTable> queryWrapper = new LambdaQueryWrapper<>();
        if (!Strings.isNullOrEmpty(vo.getLogicTableName())) {
            queryWrapper.like(LogicFactTable::getLogicTableName, vo.getLogicTableName());
        }
        // TODO 其他筛选条件 ... ...
        Page<LogicFactTable> page = new Page<>(vo.getCurrent(), vo.getSize());
        IPage<LogicFactTable> result = logicFactTableMapper.selectPage(page, queryWrapper);

        if (result.getTotal() > 0 && result.getRecords().isEmpty()) {
            long current = result.getPages();
            page = new Page<>((int) current, vo.getSize());
            result = logicFactTableMapper.selectPage(page, queryWrapper);
        }
        return result;
    }

    @Override
    public LogicFactTable queryByCode(Long tableCode) {
        return logicFactTableMapper.selectOne(
                Wrappers.<LogicFactTable>lambdaQuery().eq(LogicFactTable::getCode,tableCode)
        );
    }


}
